#include <bits/stdc++.h>
using namespace std;

/*
2874. 有序三元组中的最大值 II
已解答
中等
相关标签
相关企业
提示
给你一个下标从 0 开始的整数数组 nums 。

请你从所有满足 i < j < k 的下标三元组 (i, j, k) 中，找出并返回下标三元组的最大值。如果所有满足条件的三元组的值都是负数，则返回 0 。

下标三元组 (i, j, k) 的值等于 (nums[i] - nums[j]) * nums[k] 。

 

示例 1：

输入：nums = [12,6,1,2,7]
输出：77
解释：下标三元组 (0, 2, 4) 的值是 (nums[0] - nums[2]) * nums[4] = 77 。
可以证明不存在值大于 77 的有序下标三元组。
示例 2：

输入：nums = [1,10,3,4,19]
输出：133
解释：下标三元组 (1, 2, 4) 的值是 (nums[1] - nums[2]) * nums[4] = 133 。
可以证明不存在值大于 133 的有序下标三元组。 
示例 3：

输入：nums = [1,2,3]
输出：0
解释：唯一的下标三元组 (0, 1, 2) 的值是一个负数，(nums[0] - nums[1]) * nums[2] = -3 。因此，答案是 0 。
 

提示：

3 <= nums.length <= 105
1 <= nums[i] <= 106
*/

// 法一

// 前缀 后缀 遍历
class Solution {
public:
	long long maximumTripletValue(vector<int>& nums) {
		// prefix
		int n = nums.size();
		if (n < 3) return 0;
		// 前缀最大值数组 preMax[j] j 之前的最大 nums[i]
		vector<long long> preMax(n, 0);
		preMax[1] = nums[0];
		for (int i = 2; i < n; i++) {
			preMax[i] = max(preMax[i - 1], (long long)nums[i - 1]);
		}

		// 后缀最大值
		vector<long long> sufferMax(n, LLONG_MIN);
		preMax[1] = nums[0];
		for (int i = n - 2; i >= 0; i--) {
			sufferMax[i] = max(sufferMax[i + 1], (long long)nums[i + 1]);
		}

		long long ans = 0;
		for (int i = 1; i < n - 1; i++) {
			long long cur = (preMax[i] - nums[i]) * sufferMax[i];
			if(cur > ans)   ans = cur;
		}
		return ans > 0 ? ans : 0;
	}
};

// 法二

// 贪心
class Solution {
	public:
	long long maximumTripletValue(vector<int>& nums) {
		// 贪心
		long long ans = 0;
		int iMax = nums[0];
		int tailMax = 0;

		for(int i = 1; i < nums.size(); i++) {
			int num = nums[i];
			// 计算当前三元组的值
			// i >= 2
			if (i >= 2)     ans = max(ans, (long long)tailMax * num);

			// 更新差值的最大值
			tailMax = max(tailMax, iMax - num);
			// 更新 iMax（到 i 为止的最大值）
			iMax = max(iMax, num);
		}
		return ans > 0 ? ans : 0;
	}
};

/**
 * 方法 1：前后缀数组（时间复杂度 O(n)，空间复杂度 O(n)）
 * 方法 2：贪心优化（时间复杂度 O(n)，空间复杂度 O(1)）
 */